﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using Microsoft.Practices.Composite.Events;
using VisualStock.Infrastructure;
using VisualStock.Modules.StockMarket.Models;
using Microsoft.Practices.Composite.Presentation.Events;
using VisualStock.Infrastructure.Models;
using VisualStock.Infrastructure.Interfaces;

namespace VisualStock.Modules.StockMarket
{
    public class SettingController : ISettingController, INotifyPropertyChanged
    {
        private readonly IHistoricalDataService historicalDataService;

        // Defines the default length of the displayed days, the default date range of the historical 
        // data is from the _currentChartSettings.CurrentEndDate to _currentChartSettings.CurrentEndDate - DISPLAY_DAYS_LENGTH.
        private const double DISPLAY_DAYS_LENGTH = 120;

        #region ISettingController Members

        private DateTime _currentStartDate;

        // Defines the start date of the current displayed data
        public DateTime CurrentStartDate
        {
            get { return _currentStartDate; }
            set
            {
                {
                    if (!value.Equals(_currentStartDate))
                    {
                        _currentStartDate = value;
                        this.InvokePropertyChanged("CurrentStartDate");
                    }
                }
            }
        }

        private DateTime _currentEndDate;

        // Defines the end date of the current displayed data
        public DateTime CurrentEndDate
        {
            get { return _currentEndDate; }
            set
            {
                if (!value.Equals(_currentEndDate))
                {
                    _currentEndDate = value;
                    this.InvokePropertyChanged("CurrentEndDate");
                }
            }
        }

        private DateTime _dataStartDate;

        // This value indicates the earliest start date among the current symbols
        public DateTime DataStartDate
        {
            get { return _dataStartDate; }
            set
            {
                if (!value.Equals(_dataStartDate))
                {
                    _dataStartDate = value;
                    this.InvokePropertyChanged("DataStartDate");
                }
            }
        }

        private DateTime _dataEndDate;

        // This value indicates the lastest end date among the current symbols
        public DateTime DataEndDate
        {
            get { return _dataEndDate; }
            set
            {
                if (!value.Equals(_dataEndDate))
                {
                    _dataEndDate = value;
                    this.InvokePropertyChanged("DataEndDate");
                }
            }
        }

        private ChartTypes _primaryChartType;

        public ChartTypes PrimaryChartType
        {
            get { return _primaryChartType; }
            set
            {
                _primaryChartType = value;
                this.InvokePropertyChanged("PrimaryChartType");
            }
        }

        private ChartTypes _secondaryChartType;

        public ChartTypes SecondaryChartType
        {
            get { return _secondaryChartType; }
            set
            {
                _secondaryChartType = value;
                if (_secondaryChartType == ChartTypes.None) IsSecondaryChartVisible = Visibility.Collapsed;
                else IsSecondaryChartVisible = Visibility.Visible;
                this.InvokePropertyChanged("SecondaryChartType");
            }
        }

        private Visibility _isSecondaryChartVisible;

        public Visibility IsSecondaryChartVisible
        {
            get
            {
                return _isSecondaryChartVisible;
            }
            set
            {
                _isSecondaryChartVisible = value;
                this.InvokePropertyChanged("IsSecondaryChartVisible");
            }
        }

        private bool _view3D;

        public bool View3D
        {
            get
            {
                return _view3D;
            }
            set
            {
                // This will check if there is more than 1 point in the Chart
                if (!DataStartDate.Equals(DataEndDate))
                {
                    _view3D = value;
                    this.InvokePropertyChanged("View3D");
                }
            }
        }

        public IList<string> AvailableChartTheme { get; set; }

        public IList<ChartTypes> AvailablePrimaryChartTypes { get; set; }

        public IList<ChartTypes> AvailableSecondaryChartTypes { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public SettingController(IHistoricalDataService historicalDataService, IEventAggregator eventAggregator)
        {
            InitializeChartSettings();
            this.historicalDataService = historicalDataService;
            eventAggregator.GetEvent<NewComparisonRequestedEvent>().Subscribe(ResetChartProperties, ThreadOption.UIThread);
        }

        private void InitializeChartSettings()
        {
            AvailablePrimaryChartTypes = new List<ChartTypes> { ChartTypes.Line, ChartTypes.Area, ChartTypes.CandleStick, ChartTypes.Stock, ChartTypes.StepLine };
            AvailableSecondaryChartTypes = new List<ChartTypes> { ChartTypes.None, ChartTypes.Column, ChartTypes.Area, ChartTypes.StepLine };
            _view3D = false;
            _primaryChartType = AvailablePrimaryChartTypes[0];
            _secondaryChartType = AvailableSecondaryChartTypes[0];
            IsSecondaryChartVisible = Visibility.Collapsed;
        }

        public void ResetChartProperties(List<string> newSymbolList)
        {
            if (newSymbolList == null || newSymbolList.Count == 0) return;

            // Reset the _currentChartSettings.DataStartDate and _currentChartSettings.DataEndDate
            StockDataInfomation sdInfo;
            DateTime tempStartDate = new DateTime(), tempEndDate = new DateTime();
            for (int i = 0; i < newSymbolList.Count; i++)
            {
                sdInfo = historicalDataService.GetHistoricalDataInfo(newSymbolList[i]);
                if (i == 0)
                {
                    tempStartDate = sdInfo.StartDate;
                    tempEndDate = sdInfo.EndDate;
                }
                else
                {
                    // Set the earliest start date
                    if (sdInfo.StartDate.CompareTo(tempStartDate) < 0)
                        tempStartDate = sdInfo.StartDate;
                    // Set the latest end date
                    if (sdInfo.EndDate.CompareTo(tempEndDate) > 0)
                        tempEndDate = sdInfo.EndDate;
                }
            }

            // Reset the CurrentStartDate and _CurrentEndDate and this must be done before setting the DataStartDate and DataEndDate
            this.CurrentEndDate = tempEndDate;
            // If the default CurrentStartDate is earlier than the DataStartDate, set it as the value of DataStartDate
            DateTime defaultDateTime = tempEndDate.AddDays(-DISPLAY_DAYS_LENGTH);
            if (defaultDateTime.CompareTo(tempStartDate) < 0)
                this.CurrentStartDate = tempStartDate;
            else this.CurrentStartDate = defaultDateTime;

            this.DataStartDate = tempStartDate;
            this.DataEndDate = tempEndDate;
        }

        private void InvokePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler Handler = PropertyChanged;
            if (Handler != null) Handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
